home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PASCAL / 0187.ZIP / SNAKEPC.PAS < prev    next >
Pascal/Delphi Source File  |  1986-02-07  |  10KB  |  373 lines

  1. Program Snake;
  2. {    
  3.     This insidious game of greed was adapted for Turbo Pascal Bruce 
  4.     McKinney.  It's source is a collection of game programs for Apple 
  5.     Pascal.  It's written for the IBM PC and compatibles, but you can 
  6.     easily adapt it for other computers by changing the constants.
  7.     The border characters (NW thru EW) can be replaced if I's and 
  8.     dashes if you don't have access to the upper 128 graphics 
  9.     characters used on the IBM.  Same with the player characters.
  10.     
  11.     If you don't have a numeric keypad, replace the command characters 
  12.     with any diamond of characters.  For example, E,S,D,X.  Procedure 
  13.     NumsOn and NumsOff are for the IBM.  Delete them if you don't have 
  14.     an IBM or similar computer. }
  15.  
  16. Const
  17.  
  18.   PlayerChar = #2;
  19.   SnakeChar  = #4;
  20.   MoneyChar  = #15;
  21.   DoorChar   = #219;
  22.  
  23.   NW = #201;
  24.   NE = #187;
  25.   SW = #200;
  26.   SE = #188;
  27.   NS = #186;
  28.   EW = #205;
  29.  
  30.   Quit = 'q';
  31.  
  32.   UpCommand = '8';
  33.   DownCommand = '2';
  34.   LeftCommand = '4';
  35.   RightCommand = '6';
  36.  
  37.   SnakeLength = 5;
  38.   Height = 24;
  39.   Width = 80;
  40.   ClearScreen = 12;
  41.   MoneyWorth = 25;
  42.  
  43. Type
  44.   Coordinate = record
  45.                  X : Integer;
  46.                  Y : Integer;
  47.                end;
  48.   SnakeType = Array[1..SnakeLength] of Coordinate;
  49.   Thing = (PlayerThing,SnakeThing,MoneyThing,DoorThing,EmptyThing,ScoreThing);
  50.  
  51. Var
  52.   Snake : SnakeType;
  53.   Player, Money, Door : Coordinate;
  54.   Score, TopScore : Integer;
  55.   Left, Eaten, DoneRead, PlayAgain : Boolean;
  56.   Screen : Array[1..Width] of Array[1..Height] of Thing;
  57.   LooksLike : Array[Thing] of Char;
  58.   ch : char;
  59.   ScoreFile : File of integer;
  60.  
  61. Label 1;
  62.  
  63. {$U+}
  64.  
  65. Procedure NumsOn;
  66. begin
  67.   mem[0:1047] := mem[0:1047] or 32;
  68. end;
  69.  
  70. Procedure NumsOff;
  71. begin
  72.   mem[0:1047] := mem[0:1047] and 223;
  73. end;
  74.  
  75. Procedure ReadScore;
  76. begin
  77.   Assign(ScoreFile,'Snakscor.dta');
  78.   {$I-}Reset(ScoreFile) {$I+};
  79.   if (IOresult <> 0) then TopScore := 1
  80.     else Read(ScoreFile,TopScore);
  81.   Close(ScoreFile)
  82. end;
  83.  
  84. Procedure SaveScore;
  85. begin
  86.   Assign(ScoreFile,'Snakscor.dta');
  87.   ReWrite(ScoreFile);
  88.   Write(ScoreFile,TopScore);
  89.   Close(ScoreFile)
  90. end;
  91.  
  92. Procedure Border;
  93. Var
  94.   Col : Integer;
  95.   Row : Integer;
  96.  
  97. begin
  98.   gotoxy(1,1);write(nw);
  99.   for Col := 2 to (width-1) do write(ew);write(ne);
  100.   for Row := 2 to (Height-1) do
  101.   begin
  102.     gotoxy(1,row);write(ns);
  103.     for Col := 2 to (width-1) do write(' ');write(ns);
  104.   end;
  105.   gotoxy(1,height);write(sw);
  106.   for Col := 2 to (width-1) do write(ew);write(se);
  107. end;
  108.  
  109. Procedure Instruction;
  110. Var
  111.   Answer : Char;
  112.  
  113. begin
  114.   ReadScore;
  115.   writeln('You are about to enter the mysterious land of the Serpent');
  116.   writeln('of Kalajan.  But before you go in, consider these choices: ');
  117.   writeln;
  118.   writeln('1.  I''d like to meet this reptile before my adventure.');
  119.   writeln('2.  I already know the serpent.  Just let me in.');
  120.   writeln('3.  Reset the treasure level to the minimum amount.');
  121.   writeln;
  122.   write('So?  What''s it going to be? ');
  123.   Repeat
  124.     Read(Kbd,Answer);
  125.   Until Answer in ['1','2','3'];
  126.   if Answer = '3' then
  127.   begin
  128.     TopScore := 101;
  129.     SaveScore;
  130.     Writeln;writeln;
  131.     DoneRead := True;
  132.     Write('Now choose from the first two options above:');
  133.     Repeat
  134.       Read(Kbd,Answer);
  135.     Until Answer in ['1','2'];
  136.   end;
  137.   if Answer = '1' then
  138.   begin
  139.    ClrScr;
  140.    writeln('   Welcome to the Forest of Kalajan.  Please don''t be');
  141.    writeln('frightened by my hideous appearance.  Within the fearsome');
  142.    writeln('body of a serpent rests a peaceful and generous spirit.');
  143.    writeln('If you are master of your own passions, you will have a');
  144.    writeln('pleasant and profitable stay in this paradise. ');
  145.    writeln('   However, the forest is not without dangers.  Soon you''ll');
  146.    writeln('see a glittering gold coin.  There are many of them here.');
  147.    writeln('They look like this ',MoneyChar,'.  You may take as many as you like');
  148.    writeln('as souvenirs.  But I must warn you that greed for these coins');
  149.    writeln('has been the downfall of many of your predecessors.  You see,');
  150.    writeln('despite my gentle nature, a display of avarice drives me ');
  151.    writeln('into a blind, uncontrollable rage.');
  152.    writeln('   I''m sorry to say that during these fits I''ve sometimes');
  153.    writeln('devoured my guests.  As a matter of fact no one has ever ');
  154.    writeln('left here alive with more than $',TopScore-1,' worth of treasure.');
  155.    writeln('So take a reasonable amount.  Don''t be greedy.  There''s a ');
  156.    writeln('door that looks like this █ through which you can leave ');
  157.    writeln('when you''re ready.');
  158.    writeln('   So enjoy your stay.  Use the arrow keys to move through');
  159.    writeln('the wood and view its beauty at your leisure.  Press any key');
  160.    writeln('when you''re ready to enter the wondrous Forest of Kalajan.');
  161.    repeat
  162.      read(Kbd,Answer)
  163.    Until Answer <> '';
  164.   end;
  165. end; {Instructions}
  166.  
  167. Procedure Initialize;
  168. Var
  169.   X,Y : Integer;
  170.  
  171. begin    {Initialize}
  172.   ClrScr;
  173.   Border;
  174.   For X := 2 to Width-1 do
  175.     For Y := 2 to Height-1 do
  176.       Screen[X,Y] := EmptyThing;
  177.   Randomize;
  178.   LooksLike[SnakeThing] := SnakeChar;
  179.   LooksLike[PlayerThing] := PlayerChar;
  180.   LooksLike[MoneyThing] := MoneyChar;
  181.   LooksLike[EmptyThing] := ' ';
  182.   LooksLike[DoorThing] := DoorChar;
  183.   Left := False;
  184.   Eaten := False;
  185.   Score := 1;
  186.   gotoxy(1,25);write('Your treasure is $',Score - 1,'.');
  187.   gotoxy(45,25);Write('No one has ever got more than $',TopScore - 1,'!');
  188. end; {Initialize}      
  189.  
  190. Function FreeSpot(Pos : Coordinate) : Boolean;
  191. begin
  192.   If (Pos.x in [2..Width-1]) and (Pos.Y in [2..Height-1]) then
  193.      FreeSpot := Screen[Pos.X,Pos.Y] = EmptyThing
  194.   else
  195.      FreeSpot := False
  196. end; {FreeSpot}
  197.  
  198. Procedure MakeSpace(var NewPos : Coordinate; ForWhat : Thing);
  199. begin
  200.   With NewPos do
  201.   begin
  202.     Repeat
  203.       X := Random(Width-2)+2;
  204.       Y := Random(Height-2)+2;
  205.     Until FreeSpot(NewPos);
  206.     Gotoxy(X,Y);
  207.     Write(LooksLike[ForWhat]);
  208.     Screen[X,Y] := ForWhat
  209.   end
  210. end; {MakeSpace}
  211.  
  212. Procedure PlaceNearby(Var Near, Coord : Coordinate);
  213. var
  214.   DeltaX, DeltaY : Integer;
  215.  
  216. begin {PlaceNearby}
  217.   Repeat
  218.     Repeat
  219.       DeltaX := Random(3)-1;
  220.       DeltaY := Random(3)-1;
  221.     Until (DeltaX <> 0) or (DeltaY <> 0);
  222.     Near.X := Coord.X + DeltaX;
  223.     Near.Y := Coord.Y + DeltaY;
  224.   Until (FreeSpot(Near) or ((Near.x = Player.x) and (Near.y = Player.y)));
  225.   GotoXY(Near.X,Near.Y);
  226.   Screen[Near.X,Near.Y] := SnakeThing;
  227.   Write(LooksLike[SnakeThing])
  228. end; {PlaceNearby}
  229.  
  230. Procedure Remove(Pos : Coordinate);
  231. begin
  232.   GotoXY(Pos.X,Pos.Y);
  233.   Write(' ');
  234.   Screen[Pos.X,Pos.Y] := EmptyThing
  235. end; {Remove}
  236.  
  237. Procedure PlaceObjects;
  238. var
  239.   SnakeBody : Integer;
  240.  
  241. begin  {PlaceObjects}
  242.   MakeSpace(Snake[1],SnakeThing);
  243.   For SnakeBody := 2 to SnakeLength do
  244.     PlaceNearby(Snake[SnakeBody],Snake[SnakeBody-1]);
  245.   MakeSpace(Money,MoneyThing);
  246.   MakeSpace(Door,DoorThing);
  247.   MakeSpace(Player,PlayerThing);
  248.   gotoxy(player.x,player.y);
  249. end; {PlaceObjects}
  250.  
  251. Procedure TakeGold;
  252. begin
  253.   Score := Score + MoneyWorth;
  254.   GotoXY(19,25);
  255.   Write(Score-1);
  256.   Screen[Money.X,Money.Y] := EmptyThing;
  257.   MakeSpace(Money,MoneyThing)
  258. end; {TakeGold}
  259.  
  260. Procedure PlayerMove;
  261. Var
  262.   Command : Char;
  263.   OldPos : Coordinate;
  264.  
  265. begin
  266.   OldPos := Player;
  267.   Repeat
  268.     Read(Kbd,Command);
  269.   until Command in [UpCommand,DownCommand,LeftCommand,RightCommand,quit];
  270.   if Command = quit then begin ClrScr;NumsOff;halt end;
  271.   With Player do
  272.   begin
  273.     Case Command of
  274.       UpCommand    : If Y > 2 then Y := Y - 1;
  275.       DownCommand  : If Y < Height-1 then Y := Y + 1;
  276.       LeftCommand  : If X > 2 then X := X - 1;
  277.       RightCommand : If X < Width-1 then X := X + 1;
  278.     end; {Case}
  279.     If Screen[X,Y] = ScoreThing then Player := OldPos
  280.     else
  281.     begin
  282.       Remove(OldPos);
  283.       If ((Player.x = Money.x) and (player.y = money.y)) then TakeGold                  {*}
  284.       else if ((Player.x = Door.x) and (Player.y = Door.y)) then Left := True;
  285.       GotoXY(X,Y);
  286.       Write(PlayerChar);
  287.       Screen[X,Y] := PlayerThing
  288.     end
  289.   end
  290. end; {PlayerMove}
  291.  
  292. Function Sign(X : Integer) : Integer;
  293. begin
  294.   If X = 0 then Sign := 0
  295.   else if X > 0 then Sign := 1
  296.   else Sign := -1
  297. end; {Sign}
  298.  
  299. Procedure SnakeMove;
  300. Var
  301.   NewPos : Coordinate;
  302.   BodyPart : Integer;
  303.  
  304. begin {PlayerMove}
  305.   If Random(Score+1) <= 100 then PlaceNearby(NewPos,Snake[1])
  306.   else
  307.   begin
  308.     NewPos.X := Snake[1].X + Sign(Player.X - Snake[1].X);
  309.     NewPos.y := Snake[1].Y + Sign(Player.Y - Snake[1].Y);
  310.     If (Screen[NewPos.X, NewPos.Y] = EmptyThing) or
  311.        ((NewPos.x = Player.x) and (NewPos.y = Player.Y)) then
  312.     begin
  313.       GotoXY(NewPos.X,NewPos.Y);
  314.       Write(SnakeChar);
  315.       Screen[NewPos.X,NewPos.Y] := SnakeThing;
  316.     end
  317.     else
  318.       PlaceNearby(NewPos,Snake[1]);
  319.   end;
  320.   Remove(Snake[SnakeLength]);
  321.   If ((NewPos.x = Player.x) and (NewPos.y = Player.y)) then Eaten := True;
  322.   For BodyPart := SnakeLength Downto 2 do
  323.    begin
  324.     Snake[BodyPart] := Snake[BodyPart - 1];
  325.     If ((Snake[BodyPart].x = Player.x) and (Snake[BodyPart].y = Player.y))
  326.     then Eaten := True
  327.   end;
  328.   Snake[1] := NewPos;
  329.   gotoxy(Player.x,player.y)
  330. end; {SnakeMove}
  331.  
  332. Procedure FinalScore;
  333. begin
  334.   If Left then
  335.   begin
  336.     If TopScore < Score then
  337.     begin
  338.       TopScore := Score;
  339.       SaveScore;
  340.     end;
  341.     gotoXY(1,25);
  342.     write('You have escaped with $',score-1,'.');
  343.   end
  344.   else write('The snake has eaten you!');
  345.   gotoxy(30,25);write('                                                  ');
  346.   gotoxy(30,25);write('Do you want to play again? ');
  347.   repeat
  348.     read(kbd,ch)
  349.   until ch in ['y','n'];
  350.   if ch = 'y' then PlayAgain := True else PlayAgain := False;
  351.   ClrScr;
  352. end;
  353.  
  354. begin  {Main}
  355.   NumsOn;
  356.   Instruction;
  357.   1 : Initialize;
  358.   PlaceObjects;
  359.   Repeat
  360.     PlayerMove;
  361.     If not Left then SnakeMove
  362.   Until Left or Eaten;
  363.   GotoXY(1,Height);
  364.   writeln;
  365.   FinalScore;
  366.   If PlayAgain then goto 1;
  367.   NumsOff;
  368. end.
  369. keMove
  370.   Until Left or Eaten;
  371.   GotoXY(1,Height);
  372.   writeln;
  373.